package com.rattsoftware.client.widgets;

import java.util.ArrayList;
import java.util.List;

import com.extjs.gxt.ui.client.Registry;
import com.extjs.gxt.ui.client.Style.SortDir;
import com.extjs.gxt.ui.client.data.BasePagingLoadConfig;
import com.extjs.gxt.ui.client.data.BasePagingLoader;
import com.extjs.gxt.ui.client.data.PagingLoadConfig;
import com.extjs.gxt.ui.client.data.PagingLoadResult;
import com.extjs.gxt.ui.client.data.PagingLoader;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.HBoxLayout;
import com.extjs.gxt.ui.client.widget.layout.HBoxLayoutData;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.rattsoftware.client.AppMessages;
import com.rattsoftware.client.Refreshable;
import com.rattsoftware.client.RefreshableEvent;
import com.rattsoftware.client.controllers.UserListController;
import com.rattsoftware.client.model.UserSummary;
import com.rattsoftware.client.util.ProgressIndicator;
import com.rattsoftware.server.admin.model.User;

public class UserListPanel extends ContentPanel implements Refreshable {

	final AppMessages appMessages = GWT.create(AppMessages.class);

	public static final int PAGE_SIZE = 20;

	private Button newButton;
	private Button editButton;

	private Grid<UserSummary> grid;
	private LayoutContainer buttonBar;
	SearchPagingToolBar<UserSummary> toolBar;
	private PagingLoader<PagingLoadResult<UserSummary>> loader;
	private ColumnModel cm;

	public UserListPanel(final UserListController userListController) {
		setLayout(new FitLayout());

		List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
		configs.add(new ColumnConfig("ID", appMessages.id(), 20));
		configs.add(new ColumnConfig("name", appMessages.username(), 175));
		configs
				.add(new ColumnConfig("firstName", appMessages.firstName(), 175));
		configs.add(new ColumnConfig("middleName", appMessages.middleName(),
				100));
		configs.add(new ColumnConfig("lastName", appMessages.lastName(), 175));
		configs.add(new ColumnConfig("status", appMessages.status(), 100));
		configs.add(new ColumnConfig("email", appMessages.eMail(), 250));
		configs.add(new ColumnConfig("phoneNo", appMessages.phoneNo(), 100));
		cm = new ColumnModel(configs);
		cm.setHidden(0, true); // hide ID column

		toolBar = new SearchPagingToolBar<UserSummary>(PAGE_SIZE);

		loader = new BasePagingLoader<PagingLoadResult<UserSummary>>(
				new RpcProxy<PagingLoadResult<UserSummary>>() {

					@Override
					protected void load(
							Object loadConfig,
							final AsyncCallback<PagingLoadResult<UserSummary>> callback) {
						ProgressIndicator.showProgressBar();

						final PagingLoadConfig pagingLoadConfig = (PagingLoadConfig) loadConfig;
						if (pagingLoadConfig.getSortField() == null
								|| pagingLoadConfig.getSortField().trim()
										.equals("")) {
							pagingLoadConfig.setSortField("name");
							pagingLoadConfig.setSortDir(SortDir.ASC);
						}

						pagingLoadConfig.set(RemoteStoreFilterField.PARM_FIELD,
								"name");
						pagingLoadConfig.set(RemoteStoreFilterField.PARM_QUERY,
								toolBar.getSearchFilterValue());
						GWT
								.log("UserListView RpcProxy:load loadConfig pageSize="
										+ pagingLoadConfig.getLimit()
										+ " sortField="
										+ pagingLoadConfig.getSortField()
										+ " filter="
										+ toolBar.getSearchFilterValue());

						Scheduler.get().scheduleDeferred(
								new ScheduledCommand() {
									@Override
									public void execute() {
										userListController.getUsers(
												pagingLoadConfig, callback);
									}
								});
					}

				});

		loader.setRemoteSort(true);
		toolBar.bind(loader);

		ListStore<UserSummary> store = new ListStore<UserSummary>(loader);
		grid = new Grid<UserSummary>(store, cm);
		grid.setAutoExpandColumn("name");
		grid.setAutoExpandMax(10000);
		grid.setStripeRows(true);
		grid.setBorders(true);

		// new
		newButton = new Button(appMessages.newX());
		newButton.addListener(Events.Select, new Listener<ButtonEvent>() {
			@Override
			public void handleEvent(ButtonEvent be) {
				newUser(userListController);
			}
		});
		newButton.show();

		// edit
		editButton = new Button(appMessages.edit());
		editButton.addListener(Events.Select, new Listener<ButtonEvent>() {
			@Override
			public void handleEvent(ButtonEvent be) {
				editUser(userListController);
			}
		});
		editButton.show();

		User loggedInUser = Registry.get("");
		/*
		 * if (loggedInUser != null) { checkLoggedInUserPermissions(cm,
		 * loggedInUser); } else {GWT.log(
		 * "Could not find logged in user, so could not determine permissions");
		 * }
		 */

		buttonBar = new LayoutContainer();
		buttonBar.setLayout(new HBoxLayout());
		buttonBar.add(newButton, new HBoxLayoutData(new Margins(2, 5, 2, 2)));
		buttonBar.add(editButton, new HBoxLayoutData(new Margins(2, 5, 2, 2)));

		Scheduler.get().scheduleDeferred(new ScheduledCommand() {
			@Override
			public void execute() {
				// load the first set of data
				PagingLoadConfig config = new BasePagingLoadConfig(0, PAGE_SIZE);
				loader.load(config);
			}
		});
	}

	private void newUser(final UserListController userListController) {
		ProgressIndicator.showProgressBar();
		Scheduler.get().scheduleDeferred(new ScheduledCommand() {
			@Override
			public void execute() {
				userListController.forwardToNewWizard();
			}
		});
	}

	private void editUser(final UserListController userListController) {
		if (grid.getSelectionModel().getSelectedItem() != null) {
			ProgressIndicator.showProgressBar();
			Scheduler.get().scheduleDeferred(new ScheduledCommand() {
				@Override
				public void execute() {
					UserSummary userSummary = grid.getSelectionModel()
							.getSelectedItem();
					userListController.forwardToEditWizard(userSummary);
				}
			});
		} else {
			MessageBox.alert(appMessages.systemUsers(), appMessages
					.noUserSelected(), null);
		}
	}

	@Override
	public void refresh(RefreshableEvent event) {
		GWT.log("Refreshing...");
		if (event.getEventType() == RefreshableEvent.Type.UPDATE_USER) {
			User user = event.getData();
			ListStore<UserSummary> store = grid.getStore();
			UserSummary summary = getUserSummary(user.getId());
			if (summary != null) {
				summary.updateUser(user);
				store.update(summary);
			}
		} else if (event.getEventType() == RefreshableEvent.Type.CREATE_USER) {
			User user = event.getData();
			ListStore<UserSummary> store = grid.getStore();
			UserSummary summary = new UserSummary(user);
			store.add(summary);
		} else if (event.getEventType() == RefreshableEvent.Type.REFRESH_USERLIST) {
			toolBar.refresh();
		}
	}

	UserSummary getUserSummary(String userId) {
		for (UserSummary userSummary : grid.getStore().getModels()) {
			if (userId.equals(userSummary.getId())) {
				return userSummary;
			}
		}
		GWT.log("ERROR: no user summary found id=" + userId);
		return null;
	}
}
